# -*- coding: utf-8 -*-

import configparser
import logging
import os
import sys
import time

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from backTest_summary import backtest


config = configparser.ConfigParser()
config_file = 'config.ini'
if not os.path.exists(config_file):
    raise FileNotFoundError(f"Configuration file '{config_file}' not found.")


config.read(config_file)
DATA_DIR = config['DEFAULT'].get('DataDir', 'd:/Python/study_data')
LIST_DIR = config['DEFAULT'].get('List', 'list')
LOG_FILE = config['DEFAULT'].get('LogFile_Podifan', 'log_podifan.txt')

if not os.path.exists(DATA_DIR):
    os.makedirs(DATA_DIR)

filelog = True
logger = logging.getLogger('log')
logger.setLevel(logging.DEBUG)
while logger.hasHandlers():
    for i in logger.handlers:
        logger.removeHandler(i)
# file log
# formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
formatter = logging.Formatter('%(message)s')

if filelog:
    fh = logging.FileHandler(LOG_FILE, encoding='utf-8')
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(formatter)
    logger.addHandler(fh)



def test_stock(path, name):
    """
    Parameters:
    path (str): The file path to the stock data CSV file.

    Returns:
    None
    """
    # 获取股票数据
    data = pd.read_csv(path, parse_dates=['date'])

    # 获取股票数据
    data = pd.read_csv(path)

    # 确保索引是日期时间类型
    if 'date' in data.columns:
        data.index = pd.to_datetime(data.date)
    else:
        raise ValueError("The 'date' column is missing from the data.")

    # 确保索引是日期时间类型
    data.index = pd.to_datetime(data.date)

    # 计算5日均线
    data['5_day_max'] = data['close'].rolling(window=5).max()
    data['10_day_mavg'] = data['close'].rolling(window=10).mean()
    data['20_day_mavg'] = data['close'].rolling(window=20).mean()
    data['6_day_min'] = data['close'].rolling(window=6).min()
    data['3_day_min'] = data['low'].rolling(window=3).min()
    data['5_day_min'] = data['low'].rolling(window=5).min()
    data['10_day_min'] = data['low'].rolling(window=10).min()
    data['60_day_min'] = data['low'].rolling(window=60).min()
    data['120_day_min'] = data['low'].rolling(window=120).min()
    data['10_day_max'] = data['high'].rolling(window=10).max()
    data['20_day_max'] = data['high'].rolling(window=20).max()
    data['60_day_max'] = data['high'].rolling(window=60).max()
    data['120_day_max'] = data['high'].rolling(window=120).max()
    data['5_day_avg_volume'] = data['volume'].rolling(window=5).mean()

    data['falling_trend'] = np.isclose(data['3_day_min'], data['60_day_min'], atol=0.02 * data['60_day_min']) & (data['10_day_max'] < data['20_day_max']) & (data['120_day_min'] * 5 > data['60_day_max'])
    # data['falling_trend'] = np.isclose(data['5_day_min'], data['60_day_min'], atol=0.02 * data['5_day_min']) & ((data['5_day_min'] < data['90_day_max'] * 0.8))

    # 寻找放量阳线
    data['bullish_volume'] = (data['close'].pct_change() > 0.18) & data['falling_trend'].shift(1) & (data['high'] < data['60_day_min'] * 1.5) & ~((data['close'].shift(1).pct_change() > 0.02) & (data['close'].shift(2).pct_change() > 0.02))
    # & (data['close'].pct_change() < 0.1)
    data['bullish_volume_2nd_day'] = data['bullish_volume'].shift(1) & (data['close'].pct_change() > -0.06)
    data['back_test'] = (
            data['bullish_volume_2nd_day'].shift(4) |
            data['bullish_volume_2nd_day'].shift(5) |
            data['bullish_volume_2nd_day'].shift(6) |
            data['bullish_volume_2nd_day'].shift(7) |
            data['bullish_volume_2nd_day'].shift(8) |
            data['bullish_volume_2nd_day'].shift(9) |
            data['bullish_volume_2nd_day'].shift(10) |
            data['bullish_volume_2nd_day'].shift(11) |
            data['bullish_volume_2nd_day'].shift(12) |
            data['bullish_volume_2nd_day'].shift(13) |
            data['bullish_volume_2nd_day'].shift(14) |
            data['bullish_volume_2nd_day'].shift(15) |
            data['bullish_volume_2nd_day'].shift(16) |
            data['bullish_volume_2nd_day'].shift(17) |
            data['bullish_volume_2nd_day'].shift(18) |
            data['bullish_volume_2nd_day'].shift(19) |
            data['bullish_volume_2nd_day'].shift(20) |
            data['bullish_volume_2nd_day'].shift(21) |
            data['bullish_volume_2nd_day'].shift(22) |
            data['bullish_volume_2nd_day'].shift(23) |
            data['bullish_volume_2nd_day'].shift(24) |
            data['bullish_volume_2nd_day'].shift(25)
                                ) & (data['close'] == data['6_day_min']) & (data['close'] < data['60_day_min'] * 1.25)
    #  & (np.isclose(data['close'], data['60_day_min'], atol=0.05 * data['close']) | np.isclose(data['close'], data['20_day_mavg'], atol=0.02 * data['close']) | np.isclose(data['close'], data['10_day_mavg'], atol=0.02 * data['close']))
    # data['watch_signal'] = (data['close'].pct_change() >= 0.02) & (data['close'] * data['outstanding_share'] < 30000000000) & (data['close'] >= data['close'].shift(1)) & (data['close'] >= data['close'].shift(2)) & (data['close'] >= data['close'].shift(3)) & (data['volume'] >= data['5_day_avg_volume']) & (data['close'] >= data['5_day_mavg']) & (data['close'].shift(1) < data['5_day_mavg']) & (data['back_test'].shift(1) | data['back_test'].shift(2) | data['back_test'].shift(3) | data['back_test'].shift(4) | data['back_test'].shift(5) | data['back_test'].shift(6) | data['back_test'].shift(7) | data['back_test'].shift(8) | data['back_test'].shift(9) | data['back_test'].shift(10))
    data['buy_signal'] = data['back_test'] & ~(
                data['back_test'].shift(1) | data['back_test'].shift(2) | data['back_test'].shift(3) | data[
            'back_test'].shift(4) | data['back_test'].shift(5) | data['back_test'].shift(6) | data['back_test'].shift(
            7) | data['back_test'].shift(8) | data['back_test'].shift(9) | data['back_test'].shift(10) | data['back_test'].shift(11) | data['back_test'].shift(12) | data['back_test'].shift(13) | data['back_test'].shift(14) | data['back_test'].shift(15) | data['back_test'].shift(16) | data['back_test'].shift(17) | data['back_test'].shift(18))

    # data['buy_signal'] = data['watch_signal'] & ~(data['watch_signal'].shift(1) | data['watch_signal'].shift(2) | data['watch_signal'].shift(3) | data['watch_signal'].shift(4) | data['watch_signal'].shift(5) | data['watch_signal'].shift(6) | data['watch_signal'].shift(7) | data['watch_signal'].shift(8) | data['watch_signal'].shift(9) | data['watch_signal'].shift(10))

    # 检查生成的买入信号日期
    buy_signal_dates = data[data['buy_signal']].index
    # print(f"Buy signal dates: {buy_signal_dates}")
    dict = {}
    dict[os.path.basename(path).split('.')[0]] = [str(date)[:10] for date in buy_signal_dates]
    # print(dict)
    data.to_csv(r'd:\Python\study_data\code_DataFrame.csv')
    return dict


def find_all_buys(path):
    all_buys_code = {}
    all_buys_name = {}
    list_df = pd.read_csv(f'{LIST_DIR}/stocks.csv')
    stocks = dict(zip(list_df['名称'], list_df['代码']))
    for name, code in stocks.items():
        if 'ST' not in name:
            try:
                buys = test_stock(f'{DATA_DIR}/{path}/{code}.csv', name)
                for key, value in buys.items():
                    for date in value:
                        if date in all_buys_code:
                            all_buys_code[date].append(key)
                            all_buys_name[date].append(name)
                        else:
                            all_buys_code[date] = [key]
                            all_buys_name[date] = [name]
            except FileNotFoundError:
                continue

    all_buys_code_df = pd.DataFrame.from_dict(all_buys_code, orient='index').sort_index()
    all_buys_name_df = pd.DataFrame.from_dict(all_buys_name, orient='index').sort_index()
    all_buys_code_df.to_csv('all_buys_20_day_line.csv')
    all_buys_name_df.to_csv('all_buys_20_day_line_name.csv')


if __name__ == '__main__':
    begin_time = time.time()
    # find_all_buys('stocks_test')
    find_all_buys('stocks')

    end_time = time.time()
    run_time = round(end_time - begin_time)
    hour = run_time // 3600
    minute = (run_time - 3600 * hour) // 60
    second = run_time - 3600 * hour - 60 * minute
    print(f'该程序运行时间：{hour}小时{minute}分钟{second}秒')

    begin_time = time.time()

    test = 'all_buys_20_day_line.csv'
    backtest(test)

    end_time = time.time()
    run_time = round(end_time - begin_time)
    hour = run_time // 3600
    minute = (run_time - 3600 * hour) // 60
    second = run_time - 3600 * hour - 60 * minute
    print(f'该程序运行时间：{hour}小时{minute}分钟{second}秒')